import datetime

from sqlalchemy import Table, Column, ForeignKey
from sqlalchemy.orm import relation, backref, mapper
from sqlalchemy.types import BigInteger, Integer, String, DateTime, Text, Float, Boolean

from fidoweb.model.meta import Base

"""
Rules
	1. Tables and Inner relations are sorted in alphabet order, and Inner relations are defined after Tables
	2. About relations:
		For m-m and o-o relations: 'relation' defined in the first element of the relation
		For o-m(m-o) relations: 'relation' defined in the element of 'm' side
"""

"""
Tables
	Group
	GroupTopic
	GroupTopicPost
	Tag
	TagType
"""

"""
Inner relations
	Group(topics) o-m GroupTopic(group)
	Group(tags) m-m Tag(groups)
	GroupTopic(posts) o-m GroupTopicPost(topic)
	Tag(type) m-o TagType(tags)
"""

"""
Outer relations
	Group(founder) m-o User(foundedGroups)
	Group(admins) m-m User(adminGroups) (describing the administrators of a group)
	Group(users) m-m User(groups) (describing whether a user is in a group)
	Group(schools) m-m School(groups) (describing whether a group is in certain school)
	GroupTopic(user) m-o User(groupTopics)
	GroupTopicPost(user) m-o User(groupTopicPosts)
"""

Group_t = Table('groups', Base.metadata,
	Column('id', BigInteger, primary_key = True),
	Column('name', String(64), index = True),
	Column('description', Text),
	Column('isAuthentic', Boolean),
	Column('visitCount', BigInteger, index = True),
	Column('userCount', Integer, index = True),
	Column('topicCount', Integer, index = True),
	Column('founder_id', BigInteger, ForeignKey('users.id')),
	Column('ranking', Float, index = True),
	Column('createTime', DateTime(timezone = True), index = True),
	Column('updateTime', DateTime(timezone = True), index = True)
)

GroupTopic_t = Table('groupTopics', Base.metadata,
	Column('id', BigInteger, primary_key = True),
	Column('title', Text),
	Column('content', Text),
	Column('postCount', Integer, index = True),
	Column('createTime', DateTime(timezone = True), index = True),
	Column('updateTime', DateTime(timezone = True), index = True),
	Column('user_id', BigInteger, ForeignKey('users.id')),
	Column('group_id', BigInteger, ForeignKey('groups.id')),
	Column('isTopped', Boolean, index = True)
)

GroupTopicPost_t = Table('groupTopicPosts', Base.metadata,
	Column('id', BigInteger, primary_key = True),
	Column('user_id', BigInteger, ForeignKey('users.id')),
	Column('createTime', DateTime(timezone = True), index = True),
	Column('updateTime', DateTime(timezone = True), index = True),
	Column('content', Text),
	Column('topic_id', BigInteger, ForeignKey('groupTopics.id'))
)

Tag_t = Table('tags', Base.metadata,
	Column('id', BigInteger, primary_key = True),
	Column('type_id', ForeignKey('tagTypes.id')),
	Column('name', String(64), index = True)
)

TagType_t = Table('tagTypes', Base.metadata,
	Column('id', BigInteger, primary_key = True),
	Column('name', String(64), unique = True)
)

Group_School_t = Table('groups_schools', Base.metadata,
	Column('group_id', BigInteger, ForeignKey('groups.id'), primary_key = True),
	Column('school_id', Integer, ForeignKey('schools.id'), primary_key = True),
	Column('createTime', DateTime(timezone = True), index = True)
)

Group_User_t = Table('groups_users', Base.metadata,
	Column('group_id', BigInteger, ForeignKey('groups.id'), primary_key = True),
	Column('user_id', BigInteger, ForeignKey('users.id'), primary_key = True),
	Column('createTime', DateTime(timezone = True), index = True),
	Column('updateTime', DateTime(timezone = True), index = True),
	Column('visitCount', BigInteger, index = True)
)

Group_Tag_t = Table('groups_tags', Base.metadata,
	Column('group_id', BigInteger, ForeignKey('groups.id'), primary_key = True),
	Column('tag_id', BigInteger, ForeignKey('tags.id'), primary_key = True)
)

Group_User_Management_t = Table('groups_users_management', Base.metadata,
	Column('group_id', BigInteger, ForeignKey('groups.id'), primary_key = True),
	Column('user_id', BigInteger, ForeignKey('users.id'), primary_key = True),
	Column('createTime', DateTime(timezone = True), index = True)
)

class Group(object) :
 	def __init__(self, name, description, founder_id) :
		self.name = name
		self.description = description
		self.isAuthentic = False
		self.visitCount = 0
		self.userCount = 1
		self.topicCount = 0
		self.founder_id = founder_id
		self.ranking = 0
		self.createTime = datetime.datetime.now()
		self.updateTime = datetime.datetime.now()

class GroupTopic(object) :
	def __init__(self, title, content, user_id, group_id) :
		self.title = title
		self.content = content
		self.postCount = 0
		self.createTime = datetime.datetime.now()
		self.updateTime = datetime.datetime.now()
		self.user_id = user_id
		self.group_id = group_id
		self.isTopped = False

class GroupTopicPost(object) :
	def __init__(self, content, user_id, topic_id) :
		self.content = content
		self.user_id = user_id
		self.group_id = group_id
		self.createTime = datetime.datetime.now()
		self.updateTime = datetime.datetime.now()

class Tag(object) :
	def __init__(self, name, type_id) :
		self.name = name
		self.type_id = type_id
		
class TagType(object) :
	def __init__(self, name) :
		self.name = name

class Group_School(object) :
	def __init__(self, group_id, school_id) :
		self.group_id = group_id
		self.school_id = school_id
		self.createTime = datetime.datetime.now()

class Group_User(object) :
	def __init__(self, group_id, user_id, visitCount) :
		self.group_id = group_id
		self.user_id = user_id
		self.visitCount = visitCount
		self.createTime = datetime.datetime.now()
		self.updateTime = datetime.datetime.now()

class Group_Tag(object) :
	def __init__(self, group_id, tag_id) :
		self.group_id = group_id
		self.tag_id = tag_id

class Group_User_Management(object) :
	def __init__(self, group_id, user_id) :
		self.group_id = group_id
		self.user_id = user_id
		self.createTime = datetime.datetime.now()

from fidoweb.model.user import User
from fidoweb.model.map import School
mapper(Group, Group_t, properties = {
	'id' : Group_t.c.id,
	'name' : Group_t.c.name,
	'description' : Group_t.c.description,
	'isAuthentic' : Group_t.c.isAuthentic,
	'visitCount' : Group_t.c.visitCount,
	'userCount' : Group_t.c.userCount,
	'topicCount' : Group_t.c.topicCount,
	'ranking' : Group_t.c.ranking,
	'createTime' : Group_t.c.createTime,
	'updateTime' : Group_t.c.updateTime,
	'founder	' : relation(User, backref = 'foundedGroups'),
	'users' : relation(User, secondary = Group_User_t, backref = 'groups'),
	'tags' : relation(Tag, secondary = Group_Tag_t, backref = 'groups'),
	'admins' : relation(User, secondary = Group_User_Management_t, backref = 'adminGroups'),
	'schools' : relation(School, secondary = Group_School_t, backref = 'groups')
})

mapper(GroupTopic, GroupTopic_t, properties = {
	'id' : GroupTopic_t.c.id,
	'title' : GroupTopic_t.c.title,
	'content' : GroupTopic_t.c.content,
	'postCount' : GroupTopic_t.c.postCount,
	'createTime' : GroupTopic_t.c.createTime,
	'updateTime' : GroupTopic_t.c.updateTime,
	'isTopped' : GroupTopic_t.c.isTopped,
	'user' : relation(User, backref = 'groupTopics'),
	'group' : relation(Group, backref = 'topics')
})

mapper(GroupTopicPost, GroupTopicPost_t, properties = {
	'id' : GroupTopicPost_t.c.id,
	'createTime' : GroupTopicPost_t.c.createTime,
	'updateTime' : GroupTopicPost_t.c.updateTime,
	'content' : GroupTopicPost_t.c.content,
	'user' : relation(User, backref = 'groupTopicPosts'),
	'groupTopic' : relation(GroupTopic, backref = 'posts')
})

mapper(Tag, Tag_t, properties = {
	'id' : Tag_t.c.id,
	'name' : Tag_t.c.name,
	'type' : relation(TagType, backref = 'tags')
})

mapper(TagType, TagType_t, properties = {
	'id' : TagType_t.c.id,
	'name' : TagType_t.c.name
})

mapper(Group_School, Group_School_t, properties = {
	'group_id' : Group_School_t.c.group_id,
	'school_id' : Group_School_t.c.school_id,
	'createTime' : Group_School_t.c.createTime
})

mapper(Group_User, Group_User_t, properties = {
	'group_id' : Group_User_t.c.group_id,
	'user_id' : Group_User_t.c.user_id,
	'createTime' : Group_User_t.c.createTime,
	'updateTime' : Group_User_t.c.updateTime,
	'visitCount' : Group_User_t.c.visitCount
})

mapper(Group_Tag, Group_Tag_t, properties = {
	'group_id' : Group_Tag_t.c.group_id,
	'tag_id' : Group_Tag_t.c.tag_id
})

mapper(Group_User_Management, Group_User_Management_t, properties = {
	'group_id' : Group_User_Management_t.c.group_id,
	'user_id' : Group_User_Management_t.c.user_id,
	'createTime' : Group_User_Management_t.c.createTime
})
